home *** CD-ROM | disk | FTP | other *** search
/ Sun Solutions 1997 April to September / Sun Solutions CD - APR '97 - SEP '97 (704-3778-12 Rev. H)(Sun Microsystems, Inc.)(1997).iso / products / bin / httpd / src / http_access.c next >
C/C++ Source or Header  |  1995-05-18  |  9KB  |  297 lines

  1. /*
  2.  * http_access: Security options etc.
  3.  *
  4.  * All code contained herein is covered by the Copyright as distributed
  5.  * in the README file in the main directory of the distribution of 
  6.  * NCSA HTTPD.
  7.  * 
  8.  * Based on NCSA HTTPd 1.3 by Rob McCool
  9.  *
  10.  *  03-12-95 blong
  11.  *     Added patch to fix ALLOW_THEN_DENY
  12.  * 
  13.  */
  14.  
  15.  
  16. #include "httpd.h"
  17. #include "new.h"
  18.  
  19. int in_domain(char *domain, char *what) {
  20.     int dl=strlen(domain);
  21.     int wl=strlen(what);
  22.  
  23.     if((wl-dl) >= 0)
  24.         return(!strcmp(domain,&what[wl-dl]));
  25.     else
  26.         return 0;
  27. }
  28.  
  29. int in_ip(char *domain, char *what) {
  30.     return(!strncmp(domain,what,strlen(domain)));
  31. }
  32.  
  33. int find_allow(int x, int m) {
  34.     register int y;
  35.  
  36.     if(sec[x].num_allow[m] < 0)
  37.         return 1;
  38.  
  39.     for(y=0;y<sec[x].num_allow[m];y++) {
  40.         if(!strcmp("all",sec[x].allow[m][y])) 
  41.             return 1;
  42.         if(remote_host && isalpha(remote_host[0]))
  43.             if(in_domain(sec[x].allow[m][y],remote_host))
  44.                 return 1;
  45.         if(in_ip(sec[x].allow[m][y],remote_ip))
  46.             return 1;
  47.     }
  48.     return 0;
  49. }
  50.  
  51. int find_deny(int x, int m) {
  52.     register int y;
  53.  
  54.     if(sec[x].num_deny[m] < 0)
  55.         return 1;
  56.  
  57.     for(y=0;y<sec[x].num_deny[m];y++) {
  58.         if(!strcmp("all",sec[x].deny[m][y])) 
  59.             return 1;
  60.         if(remote_host && isalpha(remote_host[0]))
  61.             if(in_domain(sec[x].deny[m][y],remote_host))
  62.                 return 1;
  63.         if(in_ip(sec[x].deny[m][y],remote_ip))
  64.             return 1;
  65.     }
  66.     return 0;
  67. }
  68.  
  69. void check_dir_access(int x, int m, int *w, int *n) {
  70.     if(sec[x].auth_type)
  71.         auth_type = sec[x].auth_type;
  72.     if(sec[x].auth_name)
  73.         auth_name = sec[x].auth_name;
  74.     if(sec[x].auth_pwfile)
  75.         auth_pwfile = sec[x].auth_pwfile;
  76.     if(sec[x].auth_grpfile)
  77.         auth_grpfile = sec[x].auth_grpfile;
  78.  
  79.     if(sec[x].order[m] == ALLOW_THEN_DENY) {
  80.     *w=0;
  81.         if(find_allow(x,m))
  82.             *w=1;
  83.         if(find_deny(x,m))
  84.             *w=0;
  85.     } else if(sec[x].order[m] == DENY_THEN_ALLOW) {
  86.         if(find_deny(x,m))
  87.             *w=0;
  88.         if(find_allow(x,m))
  89.             *w=1;
  90.     }
  91.     else
  92.         *w = find_allow(x,m) && (!find_deny(x,m));
  93.  
  94.     if(sec[x].num_auth[m])
  95.         *n=x;
  96. }
  97.  
  98. void evaluate_access(char *p, struct stat *finfo, int m, int *allow, 
  99.                      char *allow_options,FILE *out)
  100. {
  101.     int will_allow, need_auth, num_dirs;
  102.     char opts[MAX_STRING_LEN], override[MAX_STRING_LEN];
  103.     char path[MAX_STRING_LEN], d[MAX_STRING_LEN];
  104.     char errstr[MAX_STRING_LEN];
  105.     register int x,y,z,n;
  106.  
  107.     if(S_ISDIR(finfo->st_mode)) strcpy_dir(path,p);
  108.     else lim_strcpy(path,p, MAX_STRING_LEN);
  109.  
  110.     no2slash(path);
  111.  
  112.     num_dirs = count_dirs(path);
  113.     will_allow = 1; 
  114.     need_auth = -1;
  115.     auth_type = NULL; 
  116.     auth_name = NULL;
  117.     auth_pwfile = NULL;
  118.     auth_grpfile = NULL;
  119.     user[0] = '\0';
  120.     groupname[0] = '\0';
  121.     reset_mime_vars();
  122.  
  123.     for(x=0;x<num_dirs;x++) {
  124.         opts[x] = OPT_ALL;
  125.         override[x] = OR_ALL;
  126.     }
  127.  
  128.     n=num_dirs-1;
  129.     for(x=0;x<num_sec;x++) {
  130.         if(is_matchexp(sec[x].d)) {
  131.             if(!strcmp_match(path,sec[x].d)) {
  132.                 for(y=0;y<num_dirs;y++) {
  133.                     if(!(sec[x].opts & OPT_UNSET))
  134.                         opts[y] = sec[x].opts;
  135.                     override[y] = sec[x].override;
  136.                 }
  137.             }
  138.             check_dir_access(x,m,&will_allow,&need_auth);
  139.         }
  140.         else if(!strncmp(path,sec[x].d,strlen(sec[x].d))) {
  141.             for(y=count_dirs(sec[x].d) - 1;y<num_dirs;y++) {
  142.                 if(!(sec[x].opts & OPT_UNSET))
  143.                     opts[y] = sec[x].opts;
  144.                 override[y] = sec[x].override;
  145.             }
  146.             check_dir_access(x,m,&will_allow,&need_auth);
  147.         }
  148.     }
  149.     if((override[n]) || (!(opts[n] & OPT_SYM_LINKS)) || 
  150.        (opts[n] & OPT_SYM_OWNER))
  151.         {
  152.             for(x=0;x<num_dirs;x++) {
  153.                 y = num_sec;
  154.                 make_dirstr(path,x+1,d);
  155.                 if((!(opts[x] & OPT_SYM_LINKS)) || (opts[x] & OPT_SYM_OWNER)) {
  156.                     struct stat lfi,fi;
  157.  
  158.                     lstat(d,&lfi);
  159.                     if(!(S_ISDIR(lfi.st_mode))) {
  160.                         if(opts[x] & OPT_SYM_OWNER) {
  161.                             char realpath[512];
  162.                             int bsz;
  163.  
  164.                             if((bsz = readlink(d,realpath,256)) == -1)
  165.                                 goto bong;
  166.                             realpath[bsz] = '\0';
  167.                             if(realpath[0] != '/') {
  168.                                 char t[260];
  169.                                 strcpy(t,"../");
  170.                                 strcpy(&t[3],realpath);
  171.                                 make_full_path(d,t,realpath);
  172.                                 getparents(realpath);
  173.                             }
  174.                             lstat(realpath,&fi);
  175.                             if(fi.st_uid != lfi.st_uid)
  176.                                 goto bong;
  177.                         }
  178.                         else {
  179.                           bong:
  180.                             sprintf(errstr,"httpd: will not follow link %s",d);
  181.                             log_error(errstr);
  182.                             *allow=0;
  183.                             *allow_options = OPT_NONE;
  184.                             return;
  185.                         }
  186.                     }
  187.                 }
  188.                 if(override[x]) {
  189.                     parse_htaccess(d,override[x],out);
  190.                     if(num_sec != y) {
  191.                         for(z=count_dirs(sec[y].d) - 1;z<num_dirs;z++) {
  192.                             if(!(sec[y].opts & OPT_UNSET))
  193.                                 opts[z] = sec[y].opts;
  194.                             override[z] = sec[y].override;
  195.                         }
  196.                         check_dir_access(y,m,&will_allow,&need_auth);
  197.                     }
  198.                 }
  199.             }
  200.         }
  201.     if((!(S_ISDIR(finfo->st_mode))) && 
  202.        ((!(opts[n] & OPT_SYM_LINKS)) || (opts[n] & OPT_SYM_OWNER))) {
  203.         struct stat fi,lfi;
  204.         lstat(path,&fi);
  205.         if(!(S_ISREG(fi.st_mode))) {
  206.             if(opts[n] & OPT_SYM_OWNER) {
  207.                 char realpath[512];
  208.                 int bsz;
  209.                 
  210.                 if((bsz = readlink(path,realpath,256)) == -1)
  211.                     goto gong;
  212.                 realpath[bsz] = '\0';
  213.                 if(realpath[0] != '/') {
  214.                     char t[260];
  215.                     strcpy(t,"../");
  216.                     strcpy(&t[3],realpath);
  217.                     make_full_path(path,t,realpath);
  218.                     getparents(realpath);
  219.                 }
  220.                 lstat(realpath,&lfi);
  221.                 if(fi.st_uid != lfi.st_uid)
  222.                     goto gong;
  223.             }
  224.             else {
  225.               gong:
  226.                 sprintf(errstr,"httpd: will not follow link %s",path);
  227.                 log_error(errstr);
  228.                 *allow=0;
  229.                 *allow_options = OPT_NONE;
  230.                 return;
  231.             }
  232.         }
  233.     }
  234.     *allow = will_allow;
  235.     if(will_allow) {
  236.         *allow_options = opts[num_dirs-1];
  237.         if(need_auth >= 0)
  238.             check_auth(&sec[need_auth],m,out);
  239.     }
  240.     else *allow_options = 0;
  241. }
  242.  
  243. void kill_security() {
  244.     register int x,y,m;
  245.  
  246.     for(x=0;x<num_sec;x++) {
  247.         free(sec[x].d);
  248.         for(m=0;m<METHODS;m++) {
  249.             for(y=0;y<sec[x].num_allow[m];y++)
  250.                 free(sec[x].allow[m][y]);
  251.             for(y=0;y<sec[x].num_deny[m];y++)
  252.                 free(sec[x].deny[m][y]);
  253.             for(y=0;y<sec[x].num_auth[m];y++)
  254.                 free(sec[x].auth[m][y]);
  255.         }
  256.         if(sec[x].auth_type)
  257.             free(sec[x].auth_type);
  258.         if(sec[x].auth_name)
  259.             free(sec[x].auth_name);
  260.         if(sec[x].auth_pwfile)
  261.             free(sec[x].auth_pwfile);
  262.         if(sec[x].auth_grpfile)
  263.             free(sec[x].auth_grpfile);
  264.     }
  265. }
  266.  
  267. /* This function should reset the security data structure to contain only
  268.    the information given in the access configuration file.  It should be 
  269.    called after any transactions */
  270.  
  271. void reset_security() {
  272.     register int x,y,m;
  273.  
  274.     for(x=num_sec_config;x<num_sec;x++) {
  275.         free(sec[x].d);
  276.         for(m=0;m<METHODS;m++) {
  277.             for(y=0;y<sec[x].num_allow[m];y++)
  278.                 free(sec[x].allow[m][y]);
  279.             for(y=0;y<sec[x].num_deny[m];y++)
  280.                 free(sec[x].deny[m][y]);
  281.             for(y=0;y<sec[x].num_auth[m];y++)
  282.                 free(sec[x].auth[m][y]);
  283.         }
  284.         if(sec[x].auth_type)
  285.             free(sec[x].auth_type);
  286.         if(sec[x].auth_name)
  287.             free(sec[x].auth_name);
  288.         if(sec[x].auth_pwfile)
  289.             free(sec[x].auth_pwfile);
  290.         if(sec[x].auth_grpfile)
  291.             free(sec[x].auth_grpfile);
  292.     }
  293.  
  294.    num_sec = num_sec_config;
  295. }
  296.  
  297.